package com.course.web.biz;

import com.course.domain.enums.TaskType;
import com.course.domain.model.AgendaInfo;
import com.course.domain.model.AgendaWeek;
import com.course.domain.model.CourseInfo;
import com.course.domain.model.SpecWeek;
import com.course.domain.service.AgendaService;
import com.course.domain.service.CourseService;
import com.course.domain.service.SpecService;
import com.course.web.model.AgendaInfoVM;
import com.course.web.model.AgendaItemVM;
import com.course.web.model.AgendaWeekVM;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by Justin on 2017/6/13.
 */
@Component
public class WebAgendaBiz {

    private final AgendaService agendaService;
    private final CourseService courseService;
    private final SpecService specService;

    public WebAgendaBiz(AgendaService agendaService, CourseService courseService, SpecService specService) {
        this.agendaService = agendaService;
        this.courseService = courseService;
        this.specService = specService;
    }

    public AgendaInfoVM createInfo(AgendaInfoVM vm) {
        AgendaInfo info = agendaService.createInfo(toInfo(vm));
        vm.setId(info.getId());
        return vm;
    }

    public AgendaInfoVM updateInfo(AgendaInfoVM vm) {
        agendaService.updateInfo(toInfo(vm));
        return vm;
    }

    public AgendaWeekVM createWeek(AgendaWeekVM vm) {
        AgendaWeek week = agendaService.createWeek(toWeek(vm));
        vm.setId(week.getId());
        return vm;
    }

    public AgendaWeekVM updateWeek(AgendaWeekVM vm) {
        agendaService.updateWeek(toWeek(vm));
        return vm;
    }

    public AgendaInfoVM loadInfo(int studentId, int courseId) {
        AgendaInfo agendaInfo = agendaService.loadInfo(studentId, courseId);
        if (agendaInfo == null) {
            return null;
        }
        return transform(agendaInfo);
    }

    public AgendaInfoVM loadInfo(int agendaId) {
        AgendaInfo agendaInfo = agendaService.loadInfo(agendaId);
        if (agendaInfo == null) {
            return null;
        }
        return transform(agendaInfo);
    }

    public List<AgendaWeekVM> findWeek(int agendaId) {
        AgendaInfo agendaInfo = agendaService.loadInfo(agendaId);
        if (agendaInfo == null) {
            return Collections.emptyList();
        }
        int studentId = agendaInfo.getStudentId();
        int courseId = agendaInfo.getCourseId();
        CourseInfo courseInfo = courseService.loadInfo(courseId);
        int specId = courseInfo.getSpecId();
        List<SpecWeek> specWeeks = specService.findWeek(specId);
        List<AgendaWeek> agendaWeeks = agendaService.findWeek(agendaId);
        Map<Integer, AgendaWeek> agendaWeekMap = Maps.uniqueIndex(agendaWeeks, AgendaWeek::getPartIdx);
        List<AgendaWeekVM> weeks = Lists.newArrayListWithCapacity(specWeeks.size());
        for (SpecWeek specWeek : specWeeks) {
            int partIdx = specWeek.getPartIdx();
            AgendaWeek agendaWeek = agendaWeekMap.get(partIdx);
            if (agendaWeek == null) {
                agendaWeek = new AgendaWeek();
                agendaWeek.setAgendaId(agendaId);
                agendaWeek.setCourseId(courseId);
                agendaWeek.setStudentId(studentId);
                agendaWeek.setPartIdx(partIdx);
                agendaWeek.setSpecId(specId);
                agendaWeek.setStatus(1);
            }
            AgendaWeekVM week = transform(agendaWeek, specWeek);
            weeks.add(week);
        }
        return weeks;
    }

    private AgendaInfoVM transform(AgendaInfo agendaInfo) {
        AgendaInfoVM vm = new AgendaInfoVM(agendaInfo.getStudentId());
        vm.setCourseId(agendaInfo.getCourseId());
        vm.setId(agendaInfo.getId());
        vm.setDate(agendaInfo.getBeginDate());
        return vm;
    }

    private AgendaInfo toInfo(AgendaInfoVM vm) {
        AgendaInfo agendaInfo = new AgendaInfo();
        agendaInfo.setId(vm.getId());
        agendaInfo.setStudentId(vm.getStudentId());
        agendaInfo.setCourseId(vm.getCourseId());
        agendaInfo.setBeginDate(vm.getDate());
        agendaInfo.setStatus(1);
        return agendaInfo;
    }

    private AgendaWeekVM transform(AgendaWeek agendaWeek, SpecWeek specWeek) {
        AgendaWeekVM vm = new AgendaWeekVM(specWeek.getWorkdayTitle(), specWeek.getWeekendTitle());
        vm.setId(agendaWeek.getId());
        vm.setAgendaId(agendaWeek.getAgendaId());
        vm.setStudentId(agendaWeek.getStudentId());
        vm.setCourseId(agendaWeek.getCourseId());
        vm.setSpecId(agendaWeek.getSpecId());
        vm.setPartIdx(agendaWeek.getPartIdx());
        for (int i = 0; i < 7; i++) {
            int weekDay = i + 1;
            int time = agendaWeek.getByWeekDay(weekDay);
            TaskType type = specWeek.getByWeekDay(weekDay);
            AgendaItemVM item = new AgendaItemVM(vm.getPartIdx(), weekDay, type);
            item.setTime(time);
            vm.setItem(weekDay, item);
        }
        return vm;
    }

    private AgendaWeek toWeek(AgendaWeekVM vm) {
        AgendaWeek agendaWeek = new AgendaWeek();
        agendaWeek.setId(vm.getId());
        agendaWeek.setAgendaId(vm.getAgendaId());
        agendaWeek.setStudentId(vm.getStudentId());
        agendaWeek.setCourseId(vm.getCourseId());
        agendaWeek.setSpecId(vm.getSpecId());
        agendaWeek.setPartIdx(vm.getPartIdx());
        for (int i = 0; i < 7; i++) {
            int weekDay = i + 1;
            agendaWeek.setByWeekDay(weekDay, vm.getItem(weekDay).getTime());
        }
        agendaWeek.setStatus(1);
        return agendaWeek;
    }
}
